﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace MSysMonNET
{
    public class MSysCheckServices
    {
        /// <summary>
        /// This method checks if a Web Server is running on a given port
        /// </summary>
        /// <param name="hostName">the target server to check for the HTTP service</param>
        /// <param name="portNumber">the port to check for connection</param>
        /// <returns>an instance of the MSysServiceStatus with the test's result</returns>
        public MSysServiceStatus checkHTTPrunning(String hostName, int portNumber)
        {
            string server = hostName;
            int port = portNumber; 
            string page = "";
            IPHostEntry iphost;
            IPAddress ip;

            MSysServiceStatus clsStatus = new MSysServiceStatus();

            // The command sent to the HTTP Server
            string request = "GET / HTTP/1.1\r\nHost: " + server + "\r\nConnection: Close\r\n\r\n"; 

            Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
            Byte[] bytesReceived = new Byte[256];

            // Create a socket connection 
            Socket s = null;
            try
            {
                iphost = Dns.GetHostEntry(hostName);
                ip = iphost.AddressList[0];
            }
            catch (Exception ex)
            {
                clsStatus.returnCode = -4;
                clsStatus.returnMessage = "Could not establish a connection:" + ex.Message;
                clsStatus.serviceStatus = false;
                return clsStatus;
            }

            IPEndPoint ipe = new IPEndPoint(ip, port);
            Socket tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            try
                {
                    tempSocket.Connect(ipe);
                }
            catch (Exception ex)
            {
                    clsStatus.returnCode = -3;
                    clsStatus.returnMessage = "Could not establish a connection:" + ex.Message;
                    clsStatus.serviceStatus = false;
                    return clsStatus;
            }

            if (tempSocket.Connected)
            {
                s = tempSocket;
            }

            // Verify if connected
            if (s == null)
            {
                clsStatus.returnCode = -1;
                clsStatus.returnMessage = "Could not connect to server.";
                clsStatus.serviceStatus = false;
                return clsStatus;
            }
            else
            {
                try
                {
                    // Send the request to the server.
                    s.Send(bytesSent, bytesSent.Length, 0);

                    //Receive the server home page content.
                    int bytes = 0;

                    do
                    {
                        bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
                        page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
                    }
                    while (bytes > 0);
                }
                catch (Exception ex)
                {
                    //failure to get response
                    clsStatus.returnCode = -2;
                    clsStatus.returnMessage = "Could not get HTTP response from server:" + ex.Message;
                    clsStatus.serviceStatus = false;
                    return clsStatus;

                }
            }

            //SUCCESS
            clsStatus.returnCode = 0;
            clsStatus.returnMessage = "Test Successful.";
            clsStatus.serviceStatus = true;
            return clsStatus;
        }
        /// <summary>
        /// This method checks if a FTP Server is running on a given port
        /// </summary>
        /// <param name="hostName">the target server to check for the FTP service</param>
        /// <param name="portNumber">the port to check for connection</param>
        /// <returns>an instance of the MSysServiceStatus with the test's result</returns>
        public MSysServiceStatus checkFTPrunning(String hostName, int portNumber)
        {

            MSysServiceStatus clsStatus = new MSysServiceStatus();

            try
            {
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPHostEntry iphost = Dns.GetHostEntry(hostName);
                IPAddress ip = iphost.AddressList[0];
                IPEndPoint iep = new IPEndPoint(ip, portNumber);

                s.Connect(iep);

                string response;
                string cmd = "USER anonymous\r\n";
                int sizeReceived;
                Byte[] readBytes = new Byte[1024];

                s.Send(Encoding.ASCII.GetBytes(cmd), cmd.Length, 0);
                sizeReceived = s.Receive(readBytes);

                response = Encoding.ASCII.GetString(readBytes, 0, sizeReceived);

            }
            catch (Exception ex)
            {

                // Connection Was not successful
                clsStatus.returnCode = -1;
                clsStatus.returnMessage = "Could not perform valid FTP test:" + ex.Message;
                clsStatus.serviceStatus = false;
                return clsStatus;

            }

            //SUCCESS
            clsStatus.returnCode = 0;
            clsStatus.returnMessage = "Test Successful.";
            clsStatus.serviceStatus = true;
            return clsStatus;

        }
    
    }

    /// <summary>
    /// Class that represents the return of a test to a service status
    /// </summary>
    public class MSysServiceStatus
    {
        /// <summary>
        /// usually a negative value for unsuccessful tests, zero or positive for success
        /// </summary>
        public int returnCode { get; set; }
        /// <summary>
        /// in case of failure, the exception error message is placed here
        /// </summary>
        public String returnMessage { get; set; }
        /// <summary>
        /// indicates whether the test was successful or not
        /// </summary>
        public bool serviceStatus { get; set; }
    }
}
